<template>
	<div>
		<a-row class="mb-2" v-if="props.hiddenFlag==null||!props.hiddenFlag">
			<a-col :span="24">
				<a-card>
					<a-space>
						<a-range-picker
							:defaultValue="[searchConfig.startDate, searchConfig.endDate]"
							:show-time="{ format: 'YYYY-MM-DD' }"
							format="YYYY-MM-DD"
							:placeholder="['开始时间', '结束时间']"
							@ok="onOk"
						/>

						<a-input-search
							placeholder="请输入关键字"
							v-model:value="searchConfig.keywords"
							@search="tableRef.refresh()"
						>
						</a-input-search>

						<a-input-search placeholder="请输入tid" v-model:value="searchConfig.tid" @search="tableRef.refresh()">
						</a-input-search>

						<a-select
							v-model:value="searchConfig.logStoreTypeCode"
							allow-clear
							placeholder="请选择日志存储方式"
							size="normal"
						>
							<a-select-option v-for="item in logStoreTypeCodeList" :key="item" :label="item" :value="item" />
						</a-select>

						<a-button type="primary" @click="tableRef.refresh()">查询</a-button>
					</a-space>
				</a-card>
			</a-col>
		</a-row>

		<a-row class="mb-2" v-if="props.hiddenFlag==null||!props.hiddenFlag">
			<a-col :span="24">
				<a-card>
					<h-table
						ref="tableRef"
						:rowClick="rowClick"
						:paged="true"
						:columns="columns"
						:data="queryProcessLogList"
						height="calc(68vh)"
					>
					</h-table>
				</a-card>
			</a-col>
		</a-row>

		<a-modal :footer="null" v-model:open="logDetailConfig.viewFlag" width="100%">
			<a-row>
				<a-col span="3">
					<a-tabs
						v-model:activeKey="logDetailConfig.processTabKey"
						tab-position="left"
						:style="{ height: '100%' }"
						@change="oneLogView"
					>
						<a-tab-pane v-for="processTab in logDetailConfig.processTabs" :key="processTab.code" :tab="processTab.name">
						</a-tab-pane>
					</a-tabs>
				</a-col>
				<a-col span="20">
					<div style="height: 600px; width: 100%">
						<ProcessLogView v-if="logDetailConfig.logViewType == 'log'" ref="logView" :lf="lf"></ProcessLogView>

						<Flow
							ref="flowRef"
							:initCallBack="processLogAppend"
							:toolbarConfig="toolbarConfig"
							:childFlowFlag="true"
							:componentsViewConfig="componentsViewConfig"
							:floatToolbarViewConfig="floatToolbarViewConfig"
							v-if="logDetailConfig.logViewType != 'log' && logDetailConfig.processVersionId"
							:id="logDetailConfig.processVersionId"
						></Flow>
					</div>
				</a-col>

				<a-col span="1">
					&nbsp;
					<a-tag @click="viewChosenFunc">{{ logDetailConfig.logViewType == 'log' ? '视图' : '日志' }}</a-tag>
				</a-col>
			</a-row>
		</a-modal>
	</div>
</template>

<script setup>
	import processLogApi from '@/api/process/processLogApi'
	import { message } from 'ant-design-vue'
	import dayjs from 'dayjs'
	import processVersionApi from '@/api/process/processVersionApi'
	import ProcessLogView from '@/views/process/engine/processLogView.vue'
	import { customMountFunc } from '@/views/process/engine/functions.js'
	import { nextTick } from '@/utils'
	import Flow from '@/views/process/engine/index.vue'
	import processTestApi from '@/api/process/processTestApi'

	const logDetailConfig = ref({
		viewFlag: false,
		tabKey: '1',
		processTabKey: 'all',
		processTabs: [],
		logViewType: 'log',
		processVersionId: null
	})
	const props = defineProps(['hiddenFlag',"tid","logStoreTypeCode","logViewFlag"])
	const logStoreTypeCodeList =ref(['db','local'])

	watch(()=>props.logViewFlag,(n,o)=>{
		if(!n){
			return;
		}
		logDetailConfig.value.viewFlag = n;
		searchConfig.value.logStoreTypeCode = props.logStoreTypeCode;
		appendLog({
			tid:props.tid
		});
	})
	const flowRef = ref()
	const toolbarConfig = ref({
		viewFlag: true,
		clearViewFlag: false,
		saveViewFlag: false,
		saveAndCloseViewFlag: false,
		closeViewFlag: false
	})
	const componentsViewConfig = ref({
		viewFlag: false
	})
	const floatToolbarViewConfig = ref({
		viewFlag: false
	})

	const proxy = getCurrentInstance()

	const searchConfig = ref({
		keywords: '',
		tid: null,
		logStoreTypeCode:'local',
		startDate: dayjs(new Date()),
		endDate: dayjs(new Date())
	})

	const logView = ref()

	const tableRef = ref()

	const viewChosenFunc = async () => {
		if (logDetailConfig.value.logViewType == 'log') {
			logDetailConfig.value.logViewType = 'process'
			await processChange()
		} else {
			logDetailConfig.value.logViewType = 'log'
			nextTick(() => {
				oneLogView(logDetailConfig.value.processTabKey)
			})
		}
	}
	const processChange = async () => {
		let processVersionInfo = null
		logDetailConfig.value.processVersionId = null
		//根据当前code,得到
		if (logDetailConfig.value.processTabKey == 'all') {
			//找到主流程的信息
			processVersionInfo = findMainProcessInfo()
		} else {
			processVersionInfo = findOneProcessInfo(logDetailConfig.value.processTabKey)
		}

		let processVersionId = await queryProcessVersionId(processVersionInfo.processId, processVersionInfo.processVersion)
		logDetailConfig.value.processVersionId = processVersionId
	}

	const processLogAppend = () => {
		//追加日志
		let jsonList = []
		if (logDetailConfig.value.processTabKey == 'all') {
			jsonList = getLogAllJson()
		} else {
			jsonList = getLogJsonByCode(logDetailConfig.value.processTabKey)
		}
		for (let b of jsonList) {
			flowRef.value.logAndStepStatusFormat(b)
		}
	}
	const sortJsonLogList = (jsonList) => {
		jsonList = jsonList.sort(function (a, b) {
			return Date.parse(a.timestamp) - Date.parse(b.timestamp)
		})
		return jsonList
	}
	const getLogJsonByCode = (code) => {
		let cb = code.split('@')
		let jsonList = []

		let flag = isMainProcessInfo(cb[1], cb[2])

		if (flag == 1) {
			return getLogAllJson()
		}
		let details = instanceMap.value.get(cb[0])
		if (details.length <= 0) {
			return
		}
		for (let det of details) {
			let feature = det.feature
			if (!feature) {
				continue
			}
			if (!(det.processName == cb[1] && det.processVersion == cb[2])) {
				continue
			}
			let json = JSON.parse(feature)
			if (json.length <= 0) {
				continue
			}
			for (let b of json) {
				jsonList.push(b)
			}
		}
		return sortJsonLogList(jsonList)
	}
	const getLogAllJson = () => {
		let jsonList = []
		for (let instance of instanceMap.value) {
			let details = instance[1]
			if (details.length <= 0) {
				continue
			}
			for (let det of details) {
				let feature = det.feature
				if (!feature) {
					continue
				}
				let json = JSON.parse(feature)
				if (json.length <= 0) {
					continue
				}
				for (let b of json) {
					jsonList.push(b)
				}
				// for (let b of json) {
				// //	flowRef.value.logAndStepStatusFormat(b)
				// }
			}
		}
		return sortJsonLogList(jsonList)
	}
	const findOneProcessInfo = (code) => {
		let cb = code.split('@')
		let processVersionInfo = {}

		let details = instanceMap.value.get(cb[0])
		if (details.length <= 0) {
			return
		}
		for (let det of details) {
			let feature = det.feature
			if (!feature) {
				continue
			}
			if (!(det.processName == cb[1] && det.processVersion == cb[2])) {
				continue
			}
			processVersionInfo.processId = det.processId
			processVersionInfo.processVersion = det.processVersion
			break
		}
		return processVersionInfo
	}
	const isMainProcessInfo = (processName, processVersion) => {
		let processVersionInfo = {}
		let mainProcessFlag = 0
		for (let instance of instanceMap.value) {
			let details = instance[1]
			if (details.length <= 0) {
				continue
			}
			let detail = details[0]
			//主流程
			if (detail.processName == processName && detail.processVersion == processVersion) {
				mainProcessFlag = detail.mainProcessFlag
				break
			}
		}
		return mainProcessFlag
	}
	const findMainProcessInfo = () => {
		let processVersionInfo = {}
		for (let instance of instanceMap.value) {
			let instanceId = instance[0]
			let details = instance[1]
			if (details.length <= 0) {
				continue
			}
			let detail = details[0]
			//主流程
			if (detail.mainProcessFlag == 1) {
				processVersionInfo.processId = detail.processId
				processVersionInfo.processVersion = detail.processVersion
				break
			}
		}
		return processVersionInfo
	}
	const lf = ref({})
	customMountFunc(lf.value)

	const logCardStyle = ref({
		width: '100%'
	})

	const onOk = (value) => {
		let startDate = value[0]
		let endDate = value[1]
		searchConfig.value.startDate = startDate
		searchConfig.value.endDate = endDate
	}

	const queryProcessVersionId = async (processId, processVersion) => {
		let data = await processVersionApi.getByProcessIdAndVersion({
			processId,
			processVersion
		})
		return data.id
	}

	const columns = ref([
		{
			title: '主流程',
			dataIndex: 'processName',
			key: 'processName',
			ellipsis: true
		},
		{
			title: '主流程版本',
			dataIndex: 'processVersion',
			key: 'processVersion',
			ellipsis: true
		},
		{
			title: 'tid',
			dataIndex: 'tid',
			key: 'tid',
			ellipsis: true
		},

		{
			title: '开始日期',
			dataIndex: 'startTime',
			key: 'startTime',
			ellipsis: true
		},
		{
			title: '结束日期',
			dataIndex: 'endTime',
			resizable: true,
			key: 'endTime',
			ellipsis: true
		},
		{
			title: '耗时(ms)',
			dataIndex: 'cost',
			key: 'cost',
			ellipsis: true
		},
		{
			title: '状态',
			dataIndex: 'state',
			key: 'state',
			ellipsis: true,
			mapping: [
				{
					key: '0',
					value: '执行中'
				},
				{
					key: '1',
					value: '执行失败'
				},
				{
					key: '2',
					value: '执行完成'
				},
				{
					key: '3',
					value: '补偿完成'
				}
			]
		},
		{
			title: '操作',
			key: 'action',
			width: 150,
			dataIndex: 'action',
			ellipsis: true,
			fixed: 'right',
			buttonList: [
				{
					type: 'primary',
					click: (field, record) => {
						logDetailConfig.value.viewFlag = true
						nextTick(() => {
							appendLog(record)
						})
					},
					render: (record) => {
						return '日志'
					}
				},
				{
					click: (field, record) => {
						compensate(record)
					},
					render: (record) => {
						if (record.state != '1') {
							return null
						}
						return '补偿'
					}
				}
			]
		}
	])

	const instanceMap = ref(new Map())

	const compensate = async (record) => {
		let tid = await processTestApi.getTid({})

		let d = await processTestApi.compensate({
			processId: record.processId,
			processVersion: record.processVersion,
			param: null,
			tid: tid,
			logId: record.id
		})

		message.success('补偿成功，请关注是否存在错误')

		await processLogApi.updateStateById({
			id: record.id,
			state: 3
		})
		//修改日志为已经补偿
		tableRef.value.refresh()
	}

	const appendLog = async (record) => {
		logDetailConfig.value.processTabs = []
		instanceMap.value.clear()

		const detailByTid = await getDetailByTid(record)

		if (!detailByTid || detailByTid.length <= 0) {
			return
		}

		for (let b of detailByTid) {
			let array = instanceMap.value.get(b.instanceId)
			if (!array) {
				array = []
				instanceMap.value.set(b.instanceId, array)
			}
			array.push(b)
		}
		const tabs = [
			{
				code: 'all',
				name: '全部'
			}
		]
		for (let instance of instanceMap.value) {
			let instanceId = instance[0]
			let details = instance[1]
			if (details.length <= 0) {
				continue
			}

			let detail = details[0]
			if (detail.processName == null && detail.processName == null) {
				tabs.push({
					name: '没有获取到流程信息',
					code: 'notGetProcessInfo'
				})
			} else {
				tabs.push({
					name: detail.processName + '@' + detail.processVersion,
					code: instanceId + '@' + detail.processName + '@' + detail.processVersion
				})
			}
		}
		logDetailConfig.value.processTabs = tabs
		logDetailConfig.value.processTabKey = 'all'
		logDetailConfig.value.logViewType = 'log'
		nextTick(() => {
			oneLogView(logDetailConfig.value.processTabKey)
		})
	}

	const oneLogView = async (code) => {
		if (logDetailConfig.value.logViewType == 'process') {
			await processChange()
			return
		}
		if (code == 'all') {
			allLogView()
			return
		}
		let jsonList = getLogJsonByCode(code)
		logView.value.clearLog()
		for (let b of jsonList) {
			logView.value.appendLog({
				type: 'log',
				data: b
			})
		}
	}

	const allLogView = () => {
		logView.value.clearLog()
		let jsonList = getLogAllJson()
		for (let b of jsonList) {
			logView.value.appendLog({
				type: 'log',
				data: b
			})
		}
	}
	const getDetailByTid = async (record) => {
		const data = await processLogApi.getDetailByTid({
			tid: record.tid,
			logTime: record.createTime,
			logStoreTypeCode:searchConfig.value.logStoreTypeCode
		})
		return data
	}
	const queryProcessLogList = async (data) => {
		return await processLogApi.listByCondition({
			...searchConfig.value,
			...data,
			endDate: searchConfig.value.startDate.format('YYYY-MM-DD 00:00:00'),
			startDate: searchConfig.value.endDate.format('YYYY-MM-DD 00:00:00')
		})
	}
</script>

<style scoped></style>
